﻿using System.Windows;
using System.Windows.Controls;

namespace nRoute.Samples.OfficerXcel.Controls
{
    /// <remarks>
    /// - Adopted from a code project article (http://www.codeproject.com/KB/silverlight/WrapPanelSilverlight.aspx),
    ///  but changed the MeasureOverride logic
    /// </remarks>
    public class WrapPanel 
        : Panel
    {
        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(Orientation), typeof(WrapPanel), null);

        public WrapPanel()
        {
            // default orientation
            Orientation = Orientation.Horizontal;
        }

#region Properties

        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

#endregion

#region Overrides

        protected override Size MeasureOverride(Size availableSize)
        {
            var _totalWidth = 0d;
            var _totalHeight = 0d;

            if (Orientation == Orientation.Horizontal)
            {
                var _largestHeight = 0d;
                var _lineWidth = 0d;

                foreach (UIElement child in Children)
                {
                    child.Measure(availableSize);

                    // we check if this items causes a roll over then we reset the vars
                    if ((_lineWidth + child.DesiredSize.Width) > availableSize.Width)
                    {
                        _totalHeight += _largestHeight;
                        _largestHeight = 0d;
                        _lineWidth = 0d;
                    }

                    if (child.DesiredSize.Height > _largestHeight)
                        _largestHeight = child.DesiredSize.Height;
                    _lineWidth += child.DesiredSize.Width;
                }

                // we add the last entry, which din't roll over
                _totalHeight += _largestHeight;
            }
            else
            {
                var _largestWidth = 0d;
                var _lineHeight = 0d;

                foreach (UIElement child in Children)
                {
                    child.Measure(availableSize);

                    // we check if this items causes a roll over then we reset the vars
                    if ((_lineHeight + child.DesiredSize.Height) > availableSize.Height)
                    {
                        _totalWidth += _largestWidth;
                        _largestWidth = 0d;
                        _lineHeight = 0d;
                    }

                    if (child.DesiredSize.Width > _largestWidth)
                        _largestWidth = child.DesiredSize.Width;
                    _lineHeight += child.DesiredSize.Height;
                }

                // we add the last entry, which din't roll over
                _totalWidth += _largestWidth;
            }

            // we return 
            return Orientation == Orientation.Horizontal ?
                new Size(availableSize.Width, _totalHeight) : new Size(_totalWidth, availableSize.Height);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            Point point = new Point(0, 0);
            int i = 0;

            if (Orientation == Orientation.Horizontal)
            {
                double largestHeight = 0.0;

                foreach (UIElement child in Children)
                {
                    child.Arrange(new Rect(point, new Point(point.X + child.DesiredSize.Width, point.Y + child.DesiredSize.Height)));

                    if (child.DesiredSize.Height > largestHeight)
                        largestHeight = child.DesiredSize.Height;

                    point.X = point.X + child.DesiredSize.Width;

                    if ((i + 1) < Children.Count)
                    {
                        if ((point.X + Children[i + 1].DesiredSize.Width) > finalSize.Width)
                        {
                            point.X = 0;
                            point.Y = point.Y + largestHeight;
                            largestHeight = 0.0;
                        }
                    }

                    i++;
                }
            }
            else
            {
                double largestWidth = 0.0;

                foreach (UIElement child in Children)
                {
                    child.Arrange(new Rect(point, new Point(point.X + child.DesiredSize.Width, point.Y + child.DesiredSize.Height)));

                    if (child.DesiredSize.Width > largestWidth)
                        largestWidth = child.DesiredSize.Width;

                    point.Y = point.Y + child.DesiredSize.Height;

                    if ((i + 1) < Children.Count)
                    {
                        if ((point.Y + Children[i + 1].DesiredSize.Height) > finalSize.Height)
                        {
                            point.Y = 0;
                            point.X = point.X + largestWidth;
                            largestWidth = 0.0;
                        }
                    }

                    i++;
                }
            }

            return base.ArrangeOverride(finalSize);
        }

#endregion

    }
}
